ProtoBuf3 C++使用篇

您所在的位置:网站首页 protobuf3 required ProtoBuf3 C++使用篇

ProtoBuf3 C++使用篇

2023-12-08 23:07| 来源: 网络整理| 查看: 265

protobuf 是用于结构化数据串行化的灵活、高效、自动化的解决方案。又如 XML,不过它更小、更快、也更简单。你只需要按照你想要的数据存储格式编写一个.proto,然后使用生成器生成的代码来读写这个数据结构。更重要的是,你甚至可以在无需重新部署程序的情况下更新数据结构。

在项目中使用protocol buffers需要经历如下三步:

     (1).定义消息格式文件,最好以proto作为后缀名

     (2).使用Google提供的protocol buffers编译器来生成代码文件,一般为.h和.cc文件,主要是对消息格式以特定的语言方式描述

     (3).使用protocol buffers库提供的API来编写应用程序 

1.先来定义一个

本消息将以客户端请求登录和服务端返回为列

syntax = "proto3"; package pt; option optimize_for = LITE_RUNTIME; message req_login { string username = 1; string password = 2; } message obj_user_info { string nickname = 1;   //昵称 string icon = 2; //头像 int64 coin = 3; //金币 string location = 4; //所属地 } //游戏数据统计 message obj_user_game_record { string time = 1; int32 kill = 2; //击杀数 int32 dead = 3; //死亡数 int32 assist= 4; //助攻数 } message rsp_login { enum RET { SUCCESS = 0; ACCOUNT_NULL = 1; //账号不存在 ACCOUNT_LOCK = 2; //账号锁定 PASSWORD_ERROR = 3; //密码错误 ERROR = 10; } int32 ret = 1; obj_user_info user_info = 2; repeated obj_user_game_record record = 3; }

2.生成目标语言代码下面的命令帮助我们将game.proto文件中定义的Protocol Buffer格式的消息编译成C++代码文件。

//SRC_DIR .proto文件存放目录 //--cpp_out 指示编译器生成C++代码,DST_DIR为生成文件存放目录 //game.proto 待编译的协议文件 protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/game.proto

由于我们在game.proto文件中定义选项optimize_for=LITE_RUNTIME,因此由该文件内生成的所有C++类的父类均为::google::protobuf::MessageLite,而非::google::protobuf::Message。MessageLite类是Message的父类,MessageLite中缺少对反射的支持,而此类功能均在Message类中提供了具体的实现。对于我们的项目而言,整个系统相对比较封闭,不会和外部程序进行交互,与此同时,我们的客户端部分又是运行在Android平台,有鉴于此,我们考虑使用LITE版本的Protocol Buffer。这样不仅可以得到更高编码效率,而且生成代码编译后所占用的资源也会更少,至于反射所能带来的灵活性和极易扩展性,对于该项目而言完全可以忽略。

3.protobuf自动生成的API

class rsp_login : public ::google::protobuf::MessageLite { public: //每一个message类都包含以下方法供你检测或操作 void CopyFrom(const rsp_login& from); void MergeFrom(const rsp_login& from); void Clear(); //清除所有字段内容,并置为空状态 bool IsInitialized() const; //检测所有required 是否初始化 int ByteSize() const; //类所占字节数 //整形变量只提供获取、修改、清除 void clear_ret(); ::google::protobuf::int32 ret() const; void set_ret(::google::protobuf::int32 value); //自定义类类型user_info bool has_user_info() const; void clear_user_info(); const ::pt::obj_user_info& user_info() const; //自定义类型,并没提供set方法,而是通过mutable_接口返回user_info的指针,可根据此指针进行赋值操作 ::pt::obj_user_info* mutable_user_info(); //返回user_info字段指针,将所有权移交给此指针,并将user_info字段置为empty状态 ::pt::obj_user_info* release_user_info(); //使用set_allocated要小心,传入的参数需要显示allocate,设置后函数内部维护此指针 void set_allocated_user_info(::pt::obj_user_info* user_info); //record为repeated的类数组类型 int record_size() const; void clear_record(); //根据id索引,返回记录的引用,const不可修改内容 const ::pt::obj_user_game_record& record(int index) const; //根据id索引,返回记录的指针,以供查看、修改 ::pt::obj_user_game_record* mutable_record(int index); //repeated类型提供add接口增加一条记录,并返回此记录的指针,以便对其赋值 ::pt::obj_user_game_record* add_record(); //提供mutable接口,并返回record字段的容器指针,可根据此指针遍历、修改 ::google::protobuf::RepeatedPtrField< ::pt::obj_user_game_record >* mutable_record(); //返回record字段的容器引用,const不可修改内容 const ::google::protobuf::RepeatedPtrField< ::pt::obj_user_game_record >& record() const; }

4.protobuf读和写

#include #include #include "game.pb.h" int main() { pt::rsp_login rsp{}; rsp.set_ret(pt::rsp_login_RET_SUCCESS); auto user_info = rsp.mutable_user_info(); user_info->set_nickname("dsw"); user_info->set_icon("345DS55GF34D774S"); user_info->set_coin(2000); user_info->set_location("zh"); for (int i = 0; i < 5; i++) { auto record = rsp.add_record(); record->set_time("2017/4/13 12:22:11"); record->set_kill(i * 4); record->set_dead(i * 2); record->set_assist(i * 5); } std::string buff{}; rsp.SerializeToString(&buff); //------------------解析---------------------- pt::rsp_login rsp2{}; if (!rsp2.ParseFromString(buff)) { std::cout


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3